#include "FIFO.h"
#include "FreeRTOS.h"

uint8_t Create_FIFO_Buffer(FIFO_BUFFER_CTRL **p_fifo_buffer)
{
	*p_fifo_buffer = (FIFO_BUFFER_CTRL *)pvPortMalloc(sizeof(FIFO_BUFFER_CTRL));
	
	if(*p_fifo_buffer == NULL){
		return 0;
	}
	
	memset(*p_fifo_buffer, 0, sizeof(FIFO_BUFFER_CTRL));
	
	return 1;
}

uint8_t FIFO_Buffer_is_Empty(FIFO_BUFFER_CTRL * p_buffer)
{
	if(p_buffer == NULL){
			return 0;
	}
	
	if(p_buffer->head == p_buffer->tail){
		return 1;
	}
	
	return 0;
}

uint8_t FIFO_Buffer_is_Full(FIFO_BUFFER_CTRL * p_buffer)
{
	if(p_buffer == NULL){
			return 0;
	}
	
	if((p_buffer->head - p_buffer->tail) == FIFO_MAX_BUFFER){
		return 1;
	}
	
	return 0;
}

uint8_t Insert_Byte_to_FIFO_Buffer(FIFO_BUFFER_CTRL * p_buffer, uint8_t byte)
{
	if(p_buffer == NULL){
			return 0;
	}
	
	if(FIFO_Buffer_is_Full(p_buffer)){
		return 0;
	}
	
	p_buffer->circular_buffer[p_buffer->head%FIFO_MAX_BUFFER] = byte;
	
	p_buffer->head++;
	
	return 1;
}

uint8_t Get_Byte_from_FIFO_Buffer(FIFO_BUFFER_CTRL * p_buffer, uint8_t *byte)
{
	if(p_buffer == NULL){
			return 0;
	}
	
	if(FIFO_Buffer_is_Empty(p_buffer)){
		return 0;
	}
	
	*byte = p_buffer->circular_buffer[p_buffer->tail%FIFO_MAX_BUFFER];
	
	p_buffer->tail++;
	
	return 1;
}

uint8_t Insert_Buff_to_FIFO_Buffer(FIFO_BUFFER_CTRL * p_buffer, uint8_t *buf, int32_t len)
{
	if(p_buffer == NULL){
			return 0;
	}
	
	int32_t unused;
	unused = FIFO_MAX_BUFFER - (p_buffer->head - p_buffer->tail);
	if(unused < len){
		return 0;
	}
	
	for(uint32_t i=0; i<len; i++){
		Insert_Byte_to_FIFO_Buffer(p_buffer, buf[i]);
	}
	
	return 1;
}

uint8_t Get_Buff_from_FIFO_Buffer(FIFO_BUFFER_CTRL * p_buffer, uint8_t *buf, int32_t len)
{
	if(p_buffer == NULL){
			return 0;
	}
	
	int32_t used;
	used = p_buffer->head - p_buffer->tail;
	if(used < len){
		return 0;
	}
	
	for(uint32_t i=0; i<len; i++){
		Get_Byte_from_FIFO_Buffer(p_buffer, &buf[i]);
	}
	
	return 1;
}

uint32_t Get_FIFO_Buffer_Avail(FIFO_BUFFER_CTRL * p_buffer)
{
	return FIFO_MAX_BUFFER - (p_buffer->head - p_buffer->tail);
}

uint8_t Get_Head_Position(FIFO_BUFFER_CTRL * p_buffer, uint32_t *pos)
{
	if(p_buffer == NULL){
			return 0;
	}
	
	*pos = p_buffer->head;
	return 1;
}

uint8_t Move_Head_Position(FIFO_BUFFER_CTRL * p_buffer, uint32_t len)
{
	if(p_buffer == NULL){
			return 0;
	}
	
	p_buffer->head = p_buffer->head + len; 
	return 1;
}

